﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FinanSoft.Entities;
using FinanSoft.Utilities;
using FinanSoft.BusinessLayer;
using System.Data.SqlClient;
using System.Xml;

namespace FinanSoft.DataLayer
{
    public class BuySaleDataManager
    {

        #region Fields
        private bool _IsError;
        private String _ErrorMessage;
        private static BuySaleDataManager _instance;
        #endregion

        #region Constructor singleton
        /// <summary>
        /// Constructor privado de la clase para permitir la implementacion del patron singleton
        /// </summary>
        private BuySaleDataManager()
        {
            _IsError = false;
            _ErrorMessage = "";
        }

        /// <summary>
        /// Metodo que obtienen la instancia existente de la clase. Si esta aun no ha sido instanciada, la instancia.
        /// </summary>
        public static BuySaleDataManager GetInstance()
        {
            if (_instance == null)
                _instance = new BuySaleDataManager();
            return _instance;
        }
        #endregion

        #region Métodos públicos

        /// <summary>
        /// Se encarga de obtener todos los encabezados de los documentos que no han sido
        /// cancelados y que son de tipo Orden (compra y venta) y de Entrada de mercancías (compra o venta)
        /// </summary>
        /// <returns>Retorna lista de los encabezados de los documentos no cancelados</returns>
        public List<Document> GetAllUncacelledDocs()
        {
            List<Document> uncancelledDocs = new List<Document>();
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_UNCANCELLED_DOCS;
                SqlParameter[] parameters = new SqlParameter[0];
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                while (result.Read())
                {
                    int idDoc = System.Convert.ToInt32(result[Constants.SP_COLUMN_DOCUMENT_ID]);
                    int docCode = System.Convert.ToInt32(result[Constants.SP_COLUMN_DOCUMENT_CODE]);
                    DateTime postingDate = (DateTime)result[Constants.SP_COLUMN_DOCUMENT_DATE_CONT];
                    DateTime deliveryExpDate = (DateTime)result[Constants.SP_COLUMN_DOCUMENT_DATE_EXP];
                    int idAuxiliarAccount = System.Convert.ToInt32(result[Constants.SP_COLUMN_DOCUMENT_ID_AUXACCOUNT]);
                    int idCurrency = System.Convert.ToInt32(result[Constants.SP_COLUMN_DOCUMENT_ID_CURRENCY]);
                    double amountBeforeTax = System.Convert.ToDouble(result[Constants.SP_COLUMN_DOCUMENT_BEFORE_TAX]);
                    double amountTax = System.Convert.ToDouble(result[Constants.SP_COLUMN_DOCUMENT_TAX]);
                    double amountTotal = System.Convert.ToDouble(result[Constants.SP_COLUMN_DOCUMENT_TOTAL]);
                    String docType = (string)result[Constants.SP_COLUMN_DOCUMENT_TYPE];
                    String status = (string)result[Constants.SP_COLUMN_DOCUMENT_STATUS];

                    Document doc = new Document(docType, idAuxiliarAccount, postingDate, deliveryExpDate, idCurrency, -1, amountBeforeTax, amountTax, amountTotal);
                    doc.idDocumento = idDoc;
                    doc.EstadoDocumento = status;
                    doc.codigoDocumento = docCode;

                    uncancelledDocs.Add(doc);
                }
                dataHelper.CloseReader();
                return uncancelledDocs;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// Se encarga de guardar un documento de x tipo en la tabla de documento contable
        /// y además devuelve el id del documento que fue insertado
        /// </summary>
        /// <param name="doc">Encabezado del documento a guardar</param>
        /// <param name="type">Tipo del documento a guardar</param>
        /// <returns>Retorna el id del documento insertado, si hubo algún error retorna -1</returns>
        public int SaveDocumentHeader(Document doc, DocType type)
        {
            int docIndex = -1;
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_SAVE_DOCUMENT;

                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_TYPE_ID, type.Id),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_AUX_ID, doc.IdCuentaAuxiliar),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_CONTA_DATE, doc.fechaEmision),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_DELIV_DATE, doc.fechaVencimiento),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_CURRENCY_ID, doc.IdMoneda),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_AMOUNT_BEFORE_TAX, doc.subTotal),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_TAX_AMOUNT, doc.impuestos),
                                             new SqlParameter(Constants.SP_PARAM_SAVE_DOCUMENT_BASE_DOC_ID, doc.BaseDocId) };

                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                while (result.Read())
                {
                    docIndex = System.Convert.ToInt32(result[Constants.SP_COLUMN_SAVE_DOCUMENT_DOC_ID]);
                }
                dataHelper.CloseReader();
                return docIndex;
            }
            catch (Exception ex)
            {
                return docIndex;
            }
        }

        /// <summary>
        /// Método que se encarga de guardar los artículos para una orden de compra o venta en específico
        /// </summary>
        /// <param name="detail">Arreglo de artículos pertenecientes a la orden</param>
        /// <param name="idDoc">Id del documento al cual pertenecen los artículos</param>
        /// <returns>Retorna si hubo o no éxito en la operación</returns>
        public bool SaveDocumentArticle(DocDetail detail, int idDoc)
        {
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_ADD_ORDER_DOC_ITEM;
                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_DOC_ID, idDoc),
                                            new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_STORE_ID, detail.StoreRoom.Id),
                                            new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_ITEM_ID, detail.Item.Id),
                                            new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_DESCRIPTION, detail.Item.Descripción),
                                            new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_QUANTITY, detail.Quantity),
                                            new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_UNIT_COST, detail.UnitCost),
                                            new SqlParameter(Constants.SP_PARAM_ADD_ORDER_DOC_ITEM_TAX_ID, detail.Tax.IdImpuesto)
                                            };
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                dataHelper.CloseReader();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Guarda la información del servicio que se facturó en el documento dado. La cantidad debe ser acorde a la moneda
        /// del documento.
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="salesAccount"></param>
        /// <param name="amount"></param>
        /// <param name="description"></param>
        /// <returns></returns>
        public bool SaveDocumentService(Document doc, Account salesAccount, double amount, string description, int taxId)
        {
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_ADD_DOC_SERVICE;
                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_ADD_DOC_SERVICE_DOC_ID, doc.idDocumento),
                                            new SqlParameter(Constants.SP_PARAM_ADD_DOC_SERVICE_ACC_ID, salesAccount.AccountID),
                                            new SqlParameter(Constants.SP_PARAM_ADD_DOC_SERVICE_AMOUNT, amount),
                                            new SqlParameter(Constants.SP_PARAM_ADD_DOC_SERVICE_DESCRIPTION, description),
                                            new SqlParameter(Constants.SP_PARAM_ADD_DOC_SERVICE_TAX_ID, taxId)};
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                dataHelper.CloseReader();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        /// <summary>
        /// Método que se encarga de actualizar el id del último documento insertado
        /// para las facturas externas
        /// </summary>
        /// <param name="documentId">Id real</param>
        /// <returns>Retorna si la operación tuvo o no éxito</returns>
        public bool UpdateDocumentId(int documentId)
        {
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_UPDATE_DOC_ID;
                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_UPDATE_DOC_ID_NEW, documentId)};
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                dataHelper.CloseReader();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

    }
}
